home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / TERM.C < prev    next >
C/C++ Source or Header  |  1997-05-24  |  7KB  |  299 lines

  1. /* TERM server: access a local asy device from a tcp connection.
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  * Adapted from KA9Q's NOS 930622 by N5KNX 11/95.
  4.  */
  5. #include "global.h"
  6. #ifdef TERMSERVER
  7. #include "commands.h"
  8. #include "netuser.h"
  9. #include "smtp.h"
  10. #include "iface.h"
  11. #include "hardware.h"
  12. #include "mailbox.h"
  13. #include "asy.h"
  14. #ifdef UNIX
  15. #include "unixasy.h"
  16. #else
  17. #include "n8250.h"
  18. #endif
  19. #include "devparam.h"
  20. #ifndef MSDOS
  21. #include "telnet.h"
  22. #endif
  23.  
  24. #if !defined(_lint)
  25. static char rcsid[] OPTIONAL = "$Id: term.c,v 1.12 1997/05/24 13:11:12 root Exp root $";
  26. #endif
  27.  
  28. static void termserv (int s,void *unused,void *p);
  29. static void termrx (int s,void *p1,void *p2);
  30. static int prompting_read (const char *prompt, int s, char *buf, int buflen);
  31.  
  32. static const char termlistener[] = "TERM listener";
  33. static const char termserver[] = "TERM server";
  34. static int S_term = -1;
  35.  
  36. static char *Termpass = NULLCHAR;
  37. struct portlist {
  38.     char *portname;
  39.     struct portlist *next;
  40. };
  41. #define NULLPL (struct portlist *)NULL
  42. static struct portlist *Termports = NULLPL;
  43.  
  44.  
  45. /* Start up TCP term server */
  46. int
  47. term1 (argc, argv, p)
  48. int argc;
  49. char *argv[];
  50. void *p OPTIONAL;
  51. {
  52. int port = IPPORT_TERM;
  53.  
  54.     if (argc > 1)    {
  55.         port = atoi (argv[1]);
  56.         tprintf ("Starting Term Server on port %d\n", port);
  57.     }
  58.     return (installserver (argc, argv, &S_term, termlistener, port,
  59.         INADDR_ANY, termserver, termserv, 512, NULL));
  60. }
  61.  
  62.  
  63. /* Stop term server */
  64. int
  65. term0 (argc, argv, p)
  66. int argc OPTIONAL;
  67. char *argv[] OPTIONAL;
  68. void *p OPTIONAL;
  69. {
  70.     return (deleteserver (&S_term));
  71. }
  72.  
  73.  
  74. static void
  75. termserv(s,unused,p)
  76. int s;
  77. void *unused OPTIONAL;
  78. void *p OPTIONAL;
  79. {
  80. char buf[64];
  81. struct iface *ifp = NULLIF;
  82. struct route *rp;
  83. struct sockaddr_in fsocket;
  84. struct proc *rxproc = NULLPROC;
  85. struct asy *ap = (struct asy *) 0;
  86. struct mbuf *bp;
  87. struct portlist *pl;
  88. int (*rawsave) (struct iface *,struct mbuf *) = NULLFP((struct iface*,struct mbuf*));
  89. int i, saved = 0;
  90.     
  91.     (void) sockmode (s, SOCK_BINARY);
  92.     (void) sockowner (s, Curproc);
  93.     close_s (Curproc->output);
  94.     close_s (Curproc->input);
  95.     Curproc->output = Curproc->input = s;
  96.     (void) setflush (s, '\n');
  97.     log (s, "open term");
  98.  
  99.     /* Prompt for and check remote password */
  100.     if (Termpass) {
  101.         if (prompting_read ("Password: ", s, buf, sizeof(buf)) < 0)
  102.             goto quit;
  103.         rip (buf);
  104.         if (strcmp (buf, Termpass) != 0)    {
  105.             tputs ("Login incorrect\n");
  106.             goto quit;
  107.         }
  108.     }
  109.  
  110.     /* Prompt for desired interface. Verify that it exists, that
  111.      * we're not using it for our TCP connection, that it's an
  112.      * asynch port, and that there isn't already another tip, term
  113.      * or dialer session active on it.
  114.      */
  115.     for ( ; ; )    {
  116.         if (prompting_read ("Interface: ", s, buf, sizeof(buf)) < 0)
  117.             goto quit;
  118.         rip (buf);
  119.         if ((ifp = if_lookup (buf)) == NULLIF)    {
  120.             tprintf (Badinterface, buf);
  121.             continue;
  122.         }
  123.         for (pl = Termports; pl; pl = pl->next)
  124.             if (!strcmp (pl->portname, buf))
  125.                 break;
  126.         if (!pl) {
  127.             tprintf (Badinterface, buf);
  128.             continue;
  129.         }
  130.         if (getpeername(s,(char *)&fsocket,&i) != -1
  131.             && !ismyaddr(fsocket.sin_addr.s_addr)
  132.             && (rp = rt_lookup(fsocket.sin_addr.s_addr)) != NULLROUTE
  133.             && rp->iface == ifp)    {
  134.             tprintf ("You're using interface %s!\n", ifp->name);
  135.             continue;
  136.         }
  137.  
  138.         ap = &Asy[ifp->dev];
  139.         if (ifp->dev >= ASY_MAX || ap->iface != ifp )    {
  140.             tprintf ("Interface %s not asy port\n", buf);
  141.             continue;
  142.         }
  143.         if (ifp->raw == bitbucket)    {
  144.             tprintf("%s already in use\n", buf);
  145.             continue;
  146.         }
  147.  
  148.         /* Save output handler and temporarily redirect output to null */
  149.         rawsave = ifp->raw;
  150.         ifp->raw = bitbucket;
  151.         saved = 1;
  152.  
  153.         /* Suspend the packet input driver. Note that the transmit driver
  154.          * is left running since we use it to send buffers to the line.
  155.          */
  156.         suspend (ifp->rxproc);
  157. #ifdef POLLEDKISS
  158.         suspend (ap->poller);
  159. #endif
  160.         break;
  161.     }
  162.  
  163.     if (prompting_read ("Wink DTR? ", s, buf, sizeof(buf)) < 0)
  164.         goto quit;
  165.     if (buf[0] == 'y' || buf[0] == 'Y')    {
  166.         (void) asy_ioctl (ifp, PARAM_DTR, 1, 0);    /* drop DTR */
  167.         (void) kpause (1000L);
  168.         (void) asy_ioctl (ifp, PARAM_DTR, 1, 1);    /* raise DTR */
  169.     }
  170.  
  171.     if (prompting_read ("Turn off local echo? ", s, buf, sizeof(buf)) < 0)
  172.         goto quit;
  173.     if (buf[0] == 'y' || buf[0] == 'Y')
  174.         tprintf ("%c%c%c%c%c%c", IAC, WILL, TN_ECHO, IAC, WILL, TN_SUPPRESS_GA);
  175.  
  176.     /* Now fork into receive and transmit processes */
  177.     rxproc = newproc ("term rx", 270, termrx, s, ifp, NULL, 0);
  178.  
  179.     /* We continue to handle the TCP->asy direction */
  180.     while ((i = recvchar (s)) != EOF)    {
  181.         while (i == IAC) {
  182.             i = recvchar (s);    /* DO/DONT/WILL/WONT */
  183.             if (i == IAC)
  184.                 break;        /* escaped IAC */
  185.             i = recvchar (s);    /* opt */
  186.             i = recvchar (s);
  187.         }
  188.         if (i == '\n')
  189.             i = '\r';        /* NL => CR */
  190.         bp = pushdown (NULLBUF, 1);
  191. #if 1
  192.         bp->data[0] = (unsigned char) i;
  193. #else
  194.         bp->data[0] = (i & 0x7f);
  195. #endif
  196.         (void) asy_send (ifp->dev,bp);
  197.             ifp->lastsent = secclock();
  198.             if (i == '\r')
  199.             kwait(NULL);    /* give output buffers a chance to empty */
  200.     }
  201.  
  202. quit:
  203.     if (saved) {
  204.         killproc (rxproc);
  205.         if (ifp)    {
  206.             ifp->raw = rawsave;
  207.             resume (ifp->rxproc);
  208.         }
  209. #ifdef POLLEDKISS
  210.         if (ap)
  211.             resume (ap->poller);
  212. #endif
  213.     }
  214.     log (s, "close term");
  215.     Curproc->input = -1;  /* avoid closing s twice */
  216. }
  217.  
  218.  
  219. static void
  220. termrx (s, p1, p2)
  221. int s;
  222. void *p1;
  223. void *p2 OPTIONAL;
  224. {
  225. int c;
  226. struct iface *ifp = (struct iface *)p1;
  227.     
  228.     while ((c = get_asy (ifp->dev)) != EOF)    {
  229. #if 1
  230.         (void) usputc (s, uchar(c));
  231. #else
  232.         usputc (s, c & 0x7f);
  233. #endif
  234.         usflush (s);
  235.     }
  236. }
  237.  
  238.  
  239. static int
  240. prompting_read (prompt, s, buf, buflen)
  241. const char *prompt;
  242. int s, buflen;
  243. char *buf;
  244. {
  245. int nread;
  246.  
  247.     if (prompt) {
  248.         (void) usputs (s, prompt);
  249.         usflush (s);
  250.     }
  251.     nread = recvline (s, (unsigned char *) buf, (unsigned) buflen);
  252.     return nread;
  253. }
  254.  
  255.  
  256. int
  257. doterm (argc, argv, p)
  258. int argc;
  259. char *argv[];
  260. void *p OPTIONAL;
  261. {
  262. int i;
  263. struct portlist *pl, *pnext;
  264.  
  265.     if (argc == 1)
  266. usage:
  267.         tputs ("Usage: term ports [portlist] | term password pwstring\n");
  268.     else if (!strcmp( argv[1], "ports")) {
  269.         if (argc == 2) {
  270.             tputs ("term ports: ");
  271.             for (pl = Termports; pl; pl = pl->next)
  272.                 tprintf ("%s ", pl->portname);
  273.             tputc ('\n');
  274.         } else {
  275.             for (pl = Termports; pl; pl = pnext) {
  276.                 free (pl->portname);
  277.                 pnext = pl->next;
  278.                 free (pl);
  279.             }
  280.             Termports = NULLPL;
  281.             for (i = 2; i < argc; i++) {
  282.                 pl = mallocw (sizeof (struct portlist));
  283.                 pl->portname = strdup (argv[i]);
  284.                 pl->next = Termports;
  285.                 Termports = pl;
  286.             }
  287.         }
  288.     } else if (!strncmp (argv[1], "pass", 4)) {
  289.         if (argc != 3)
  290.             goto usage;
  291.         free (Termpass);
  292.         Termpass = strdup (argv[2]);
  293.     } else
  294.         goto usage;
  295.     return 0;
  296. }
  297.  
  298. #endif /* TERMSERVER */
  299.